package com.example.lib_processor

import com.example.lib_annotation.Nav
import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.KSPLogger
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.processing.SymbolProcessor
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSVisitorVoid
import com.google.devtools.ksp.validate
import java.io.OutputStream


private const val TAG = "MySymbolProcessor"
fun OutputStream.appendText(str: String) {
    this.write(str.toByteArray())
}

class MySymbolProcessor(private val codeGenerator: CodeGenerator, private val logger: KSPLogger) :
    SymbolProcessor {
    private val clazz = Nav::class
    private var visited = false
    override fun process(resolver: Resolver): List<KSAnnotated> {
        val symbolsWithAnnotation = resolver.getSymbolsWithAnnotation(clazz.qualifiedName!!, true)
        val list = symbolsWithAnnotation.filter { it is KSClassDeclaration }.toList()

        val kClassList = list.filterIsInstance<KSClassDeclaration>()
        kClassList.forEach {
            it.accept(Visitor(),Unit)
        }
        val ks = kClassList.firstOrNull()
        ks?.also {
            val packageName = ks.packageName.asString()
            val fs = codeGenerator.createNewFile(
                Dependencies(true, ks.containingFile!!),
                packageName,
                "MyNavigators"
            )
            val imports = kClassList.joinToString(separator = "\n") {
                val pkName = it.containingFile!!.packageName.asString()
                "import $pkName.${it.simpleName.getShortName()}Nav"
            }
            val clazzs = kClassList
                .joinToString(separator = ",") { "${it.simpleName.getShortName()}Nav::class" }
            fs.appendText("package $packageName\n")
            fs.appendText(imports)
            fs.appendText("\n")
            fs.appendText("object MyNavigators{\n")
            fs.appendText("     val list = listOf($clazzs)\n")
            fs.appendText("}")
            fs.close()
        }


        if (visited) {
            return emptyList()
        }
        visited = true
        return list.filter { !it.validate() }
    }

    inner class Visitor : KSVisitorVoid() {
        override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) {
            super.visitClassDeclaration(classDeclaration, data)
            val packageName = classDeclaration.containingFile?.packageName?.asString()
            val n = classDeclaration.simpleName.getShortName() + "Nav"
            val file = codeGenerator.createNewFile(
                Dependencies(true, classDeclaration.containingFile!!),
                packageName!!, n,
            )
            file.appendText("package $packageName\n")
            file.appendText("class ${n}{}")
            file.close()
        }
    }
}